package roborally.program.command;

import be.kuleuven.cs.som.annotate.Immutable;
import be.kuleuven.cs.som.annotate.Raw;
import roborally.itemsonboard.Robot;

/**
 * The general class representing a command that has to be executed.
 * 
 * @author Molderez Tom, 2de bach Ingenieurswetenschappen Computerwetenschappen-Elektrotechniek and Reniers Jorn, 2de bach Ingenieurswetenschappen Werktuigkunde-Computerwetenschappen
 * @version 2.0
 *
 */
public abstract class Command {
		
	/**
	 * Creates a new command with no options.
	 */
	protected Command() {
	}
	
	/**
	 * Executes this command.
	 * 
	 * @param robot The robot that should execute the command.
	 * @throws IllegalArgumentException
	 * 		When the robot is not valid.
	 * 		| !canHaveForExecution(robot)
	 */
	public abstract void execute(Robot robot) throws IllegalArgumentException;
	
	/**
	 * Search for and executes the (minimumSteps + 1) th basic command (execution command)
	 * The currentSteps is a counter that counts how many basic commands we already passed.
	 * When currentStep is equal to minimumSteps, that basic command will be executed.
	 * 
	 * @param minimumSteps The amount of basic commands we already have executed. 
	 * @param currentSteps The amount of basic commands we already passed.
	 * @param robot The robot that will be manipulated by the given program.
	 * @effect One basic command, when their are still left, will be executed.
	 * @return The new currentSteps which will increase when a basic command is found.
	 * @throws IllegalArgumentException
	 * 		When the robot is not valid.
	 */
	public abstract int next(final int minimumSteps, int currentSteps, Robot robot) 
			throws IllegalArgumentException;
	
	/**
	 * Controls if the robot is valid for execution of this command.
	 * 
	 * @param robot The robot that must be controlled.
	 * @return False if the robot is null.
	 * 		| if robot == null
	 * 		|	then result == false
	 * @return False if the robot is terminated
	 * 		| if robot.isTerminated()
	 * 		|	then result == false
	 */
	@Raw
	public boolean canHaveForExecution(Robot robot) {
		if(robot == null)
			return false;
		if(robot.isTerminated())
			return false;
		return true;
	}
	
	/**
	 * Returns a String-representation of this command.
	 * 
	 * @param leftSpaces The amount of left spaces before each word must
	 * be printed.
	 * @return A String representing the source code of this command.
	 */
	@Immutable
	public abstract String write(String leftSpaces);
	
	/**
	 * Returns a textual presentation of this class.
	 * 
	 * @return The result is the simple name, as in the Java API, of this class.
	 * 		| result == this.getClass().getSimpleName()
	 */
	@Raw
	@Override
	public String toString() {
		return this.getClass().getSimpleName();
	}
	
}
